package com.caine.gateway;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.reactive.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.reactive.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.reactive.Request;
import org.springframework.cloud.client.loadbalancer.reactive.Response;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.Random;

public class CustomerReactorServiceInstanceLoadBalancer implements ReactorServiceInstanceLoadBalancer {


    // 服务列表
    private ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider;



    public CustomerReactorServiceInstanceLoadBalancer(ObjectProvider<ServiceInstanceListSupplier> serviceInstanceListSupplierProvider) {
        this.serviceInstanceListSupplierProvider = serviceInstanceListSupplierProvider;

    }

    @Override
    @SuppressWarnings("deprecation")
    public Mono<Response<ServiceInstance>> choose(Request request) {

        ServiceInstanceListSupplier supplier = serviceInstanceListSupplierProvider.getIfAvailable();
        //request 强转为自己的request，
//        DemoRequest demoRequest = (DemoRequest ) request;
        //根据参数获取
        ServerWebExchange context = (ServerWebExchange) request.getContext();
        String userId = context.getRequest().getHeaders().get("x-asc-code").get(0);
        //获取userId的 hash值
        int hash = userId.hashCode();
        if(hash>=0){
            return   supplier.get().next().map(i->getInstanceResponse(i,hash));
        }


        //没有自定义负载均衡的将进行随机规则访问
        return supplier.get().next().map(this::getInstanceResponse);
    }


    //这里就可以计算这个用户的真实的服务实例，hash值然后取余；基本实现了功能
    private  Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances, int hash) {
        int index = hash % instances.size();
        return new DefaultResponse(instances.get(index));
    }

    /**
     * 使用随机数获取服务
     * @param instances
     * @return
     */
    @SuppressWarnings("deprecation")
    private Response<ServiceInstance> getInstanceResponse(
            List<ServiceInstance> instances) {

        if (instances.isEmpty()) {
            return new EmptyResponse();
        }
        // 随机算法
        int size = instances.size();
        Random random = new Random();
        ServiceInstance instance = instances.get(random.nextInt(size));

        return new DefaultResponse(instance);
    }
}
